# -*- coding: utf-8 -*-

"""HTMLTestRunner 截图版 selenium 版"""
import shutil
import traceback
import warnings

from selenium.webdriver.chrome.options import Options
from selenium import webdriver
import unittest, os
from ddt import ddt, data
from Basic.base_log import log
from Basic.read_excel import OpenpyxlExcel
from Basic.read_ini import ReadIni
from FindElement.performElement import PerformElement
from Basic.PATH import *
import datetime
from Basic.HTMLTestRunner_log_cn import HTMLTestRunner
from Basic.getProcess import judgeprocess

excel_path = os.path.join(log_path, fr"selenium_report_{datatime}.xlsx")
shutil.copyfile(filename, excel_path)
filename = excel_path
readini = ReadIni()

# filename = readini.get_value('excel','filename')
# sheetname = readini.get_value('excel','sheetname')
# daytime = readini.get_value('time',"daytime")
# print('测试用例：%s'% filename)
# print('测试工作表：%s'% sheetname)

excel = OpenpyxlExcel(filename=filename, sheetname=sheetname)  # 实例化excel
excel.clear_cols(filename, sheetname, col=15)  # 清空断言结果（第15列）
excel.clear_cols(filename, sheetname, col=16)  # 清空测试时间（第16列）

caseMoudleList = excel.get_caseMoudleAll_Name(filename, sheetname, )  # 用例模块集合
# print('测试模块列表：%s' % caseMoudleList)

def skip_caseMoudle_list():
    skipcase = readini.get_value('casemoudel', 'skipcase')
    skipcase_list = skipcase.split(' ')
    return skipcase_list

skip_caseMoudle_list = skip_caseMoudle_list()
# print('跳过的用例列表：%s' % skip_caseMoudle_list)

@ddt
class DdtUnitest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        # 初始化 seleium
        log.info('====================UiniTest初始化====================')
        # warnings.simplefilter('ignore', ResourceWarning)#去掉警告
        options = webdriver.ChromeOptions()
        options.add_argument("--ignore-certificate-errors")
        options.add_argument('--headless') #无头模式
        cls.driver = webdriver.Chrome(options)
        cls.driver.maximize_window()
        # 日志初始化
        cls.readini = ReadIni()
        cls.filename = filename
        cls.sheetname = sheetname
        # cls.datatime = datatime
        cls.skip_caseMoudle_list = skip_caseMoudle_list

        cls.assert_flag = None
        log.info('当前项目名称：%s' % (sheetname))  # test需要打印日志的项目名称
        log.info('测试用例：%s'% filename)
        log.info('测试工作表：%s'% sheetname)
        log.info('测试模块列表：%s' % caseMoudleList)
        log.info('跳过的用例列表：%s' % skip_caseMoudle_list)

    @classmethod
    def tearDownClass(cls):
        excel.write_excel(filename, sheetname, 2, 17, '以下为未选择执行的用例：%s'% cls.skip_caseMoudle_list)  # 测试报告中填入相关状态
        cls.driver.quit()

    def add_img(self):  # 截图
        self.imgs.append(self.driver.get_screenshot_as_base64())
        return True

    def setUp(self):
        # 在是python3.x 中，如果在这里初始化driver ，因为3.x版本 unittest 运行机制不同，会导致用力失败时截图失败
        self.imgs = []
        self.addCleanup(self.cleanup)

        # print('开始测试=========================')
    def cleanup(self):
        pass

    def get_assert(self, ast, v1, v2):
        try:
            if ast == 'assertEqual':  # --判断两个参数相等：若 a=b，则测试用例通过
                # log.info('ast:%s     v1:%s    v2:%s' % (ast, v1, v2))
                self.assertEqual(v1, v2)
            elif ast == 'assertNotEqual':
                self.assertNotEqual(v1, v2)
            elif ast == 'assertIn':  # 判断是字符串是否包含：若a在b中，则测试用例通过
                try:
                    self.assertIn(v1, v2)
                    return True
                except:
                    pass
                try:
                    self.assertIn(v2, v1)
                    return True
                except:
                    return False
            elif ast == 'assertNotIn':  #
                self.assertNotIn(v1, v2)
            elif ast == 'assertIs':  # 若a是b，则测试用例通过
                self.assertIs(v1, v2)
            elif ast == 'assertIsInstance':  # 若a是b的一个实例，则测试用例通过
                self.assertIsInstance(v1, v2)
            elif ast == 'assertNotIsInstance':  #
                self.assertNotIsInstance(v1, v2)
            elif ast == 'assertTrue':  # 判断是否为真：若x是True，则测试用例通过
                self.assertTrue(v1)
            elif ast == 'assertFalse':  #
                self.assertFalse(v1)
            elif ast == 'assertIsNone':  # 判断是否为None：若x是None，则测试用例通过
                self.assertIsNone(v1)
            elif ast == 'assertIsNotNone':  #
                self.assertIsNotNone(v1)
            else:
                log.info('-- %s --> 该assert类型未能识别，请检查后重试')
                return False
            return True
        except:
            log.info("断言异常 \n %s" % traceback.format_exc())
            return False

    @data( *caseMoudleList)
    # @unpack #数据驱动 带*号参数不能unpack
    # @unittest.skipIf(caseMoudleName in skip_caseMoudle_list )
    def test_ALL(self,caseMoudleName):
        # 跳过的用例模块 caseMoudleList
        global skip_caseMoudle_list
        if caseMoudleName in self.skip_caseMoudle_list:
            # 如果测试用例模块包含在跳过的列表里，则不执行
            log.info('跳过的用例：%s' % caseMoudleName)
        else:
            log.info('*********************************case_%s*********************************' % (caseMoudleName))
            # 初始化FindElement
            performCase = PerformElement(self.driver, self.add_img, self.get_assert)
            self.assert_flag = performCase.main_Test(caseMoudleName, self.filename, self.sheetname)
            self.add_img()
            #这里应该判断整个模块有没有出现用例没通过，没通过则false
            if self.assert_flag == False:
                # log.info(self.assert_flag)
                log.info('模块断言结果：%s' % False)
                self.assertTrue(False)
            else:log.info('模块断言结果：%s' % True)

        # if  self.readini.get_value('error', 'error_log'):
        #     os.system('taskkill /IM chromedriver.exe /F')#强制结束进程


class UnitTest_Report():

    def __init__(self):
        pass

    def UnitTest_Report(self,datatime, Testpy):
        log.info('------------测试初始化------------')
        ''' discover()方法有3个参数  
        start_dir表示测试的模块名称或者测试用例的目录
        pattern='test*.py'表示测试用例文件名的匹配规则，请注意文件名以test开头
        top_level_dir=NONE表示测试模块的顶层目录
        '''
        # 测试日志、报告输出路径
        self.report_Path = os.path.join(log_path, 'UniTestReport ' + str(datatime) + ".html")
        log.info('测试报告输出路径 ReportPath : %s' % self.report_Path)
        reportwrite = open(self.report_Path, 'wb')
        # 获取HTML框架：retry=0  测试失败重试次数。save_last_try=False，则显示所有重试的结果。=1则显示最后一次重试结果。
        runner = HTMLTestRunner(title="UniTest Report", description="UniTest Report", stream=reportwrite, verbosity=2,
                                retry=0, save_last_try=False,custom_logger=log)
        # 添加测试套件
        log.info('测试用例所在文件路径 UiniTest_path : %s' % UiniTest_path)
        discover = unittest.defaultTestLoader.discover(UiniTest_path, pattern='%s*.py' % Testpy)
        # pattern：在同一目录中自动加载符合文件名的测试用例。
        # log.info('测试用例套件 discover : %s' % discover)
        # 运行HTML框架
        runner.run(discover)
        reportwrite.close()
        # 打开测试报告
        self.open_report()

    def open_report(self):
        # 判断seleium运行结束
        while judgeprocess('chromedriver.exe'):
            time.sleep(1)
        # 启动seleium
        driver = webdriver.Chrome()
        driver.maximize_window()
        driver.get(self.report_Path)
        # 获取页面句柄
        handle = driver.current_window_handle
        # 判断页面存在则关闭程序
        while self.get_handle(driver) == handle:
            # print('当前页面：%s' % handle)
            pass
        print('该页面已关闭：%s' % handle)
        driver.quit()
        # 强制关闭进程
        os.system('taskkill /IM chromedriver.exe /F')

    def get_handle(self, driver):
        try:
            # print('get :%s ' % handle)
            return driver.current_window_handle
        except:
            return None

if __name__ == "__main__":
    print('.............')
    # unittest.main()
    UnitTest_Report().UnitTest_Report(datatime, "ddtUnitest")  # 执行测试



